<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic
  PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
<topic id="topic1">
  <title id="cm20941">DECLARE</title>
  <body>
    <p id="sql_command_desc">Defines a cursor.</p>
    <section id="section2">
      <title>Synopsis</title>
      <codeblock id="sql_command_synopsis">DECLARE <varname>name</varname> [BINARY] [INSENSITIVE] [NO SCROLL] [PARALLEL RETRIEVE] CURSOR 
     [{WITH | WITHOUT} HOLD] 
     FOR <varname>query</varname> [FOR READ ONLY]</codeblock>
    </section>
    <section id="section3">
      <title>Description</title>
      <p><codeph>DECLARE</codeph> allows a user to create a cursor, which can be used to retrieve a
        small number of rows at a time out of a larger query.
        Cursors can return data either in text or in binary format using
        <codeph><xref href="./FETCH.xml#topic1" type="topic" format="dita" /></codeph>.</p>
      <note>This page describes usage of cursors at the SQL command level. If you are trying to use
        cursors inside a PL/pgSQL function, the rules are different, see <xref
          href="../../analytics/pl_sql.html" scope="external" format="html">PL/pgSQL</xref>.</note>
      <p>Normal cursors return data in text format, the same as a <codeph>SELECT</codeph> would
        produce. Since data is stored natively in binary format, the system must do a conversion to
        produce the text format. Once the information comes back in text form, the client
        application may need to convert it to a binary format to manipulate it. In addition, data in
        the text format is often larger in size than in the binary format. Binary cursors return the
        data in a binary representation that may be more easily manipulated. Nevertheless, if you
        intend to display the data as text anyway, retrieving it in text form will save you some
        effort on the client side.</p>
      <p>As an example, if a query returns a value of one from an integer column, you would get a
        string of 1 with a default cursor whereas with a binary cursor you would get a 4-byte field
        containing the internal representation of the value (in big-endian byte order). </p>
      <p>Binary cursors should be used carefully. Many applications, including psql, are not
        prepared to handle binary cursors and expect data to come back in the text format. </p>
      <note type="note">
        When the client application uses the 'extended query' protocol to issue a
            <codeph>FETCH</codeph> command, the Bind protocol message specifies whether data is to
          be retrieved in text or binary format. This choice overrides the way that the cursor is
          defined. The concept of a binary cursor as such is thus obsolete when using extended query
          protocol — any cursor can be treated as either text or binary.
      </note>
      <p>A cursor can be specified in the <codeph>WHERE CURRENT OF</codeph> clause of the
            <codeph><xref href="./UPDATE.xml#topic1" type="topic" format="dita"/></codeph> or
            <codeph><xref href="./DELETE.xml#topic1" type="topic" format="dita"/></codeph> statement
        to update or delete table data. The <codeph>UPDATE</codeph> or <codeph>DELETE</codeph>
        statement can only be run on the server, for example in an interactive psql session or
        a script. Language extensions such as PL/pgSQL do not have support for updatable cursors.
      </p>
      <p><b>Parallel Retrieve Cursors</b></p>
      <p>Greenplum Database supports a special type of cursor, a parallel retrieve cursor.
        You can use a parallel retrieve cursor to retrieve query results, in parallel,
        directly from the Greenplum Database segments, bypassing the Greenplum coordinator.</p>
      <p>Parallel retrieve cursors do not support the <codeph>WITH HOLD</codeph> clause.
        Greenplum Database ignores the <codeph>BINARY</codeph> clause when you declare a
        parallel retrieve cursor.</p>
      <p>You open a special retrieve session to each parallel retrieve cursor endpoint, and
        use the <codeph><xref href="./RETRIEVE.xml#topic1" type="topic" format="dita"/></codeph>
        command to retrieve the query results from a parallel retrieve cursor.</p>
      <p></p>
    </section>
    <section id="section4">
      <title>Parameters</title>
      <parml>
        <plentry>
          <pt>
            <varname>name</varname>
          </pt>
          <pd>The name of the cursor to be created. </pd>
        </plentry>
        <plentry>
          <pt>BINARY</pt>
          <pd>Causes the cursor to return data in binary rather than in text format.
            <note>Greenplum Database ignores the <codeph>BINARY</codeph> clause when you
            declare a <codeph>PARALLEL RETRIEVE</codeph> cursor.</note></pd>
        </plentry>
        <plentry>
          <pt>INSENSITIVE</pt>
          <pd>Indicates that data retrieved from the cursor should be unaffected by updates to the
            tables underlying the cursor while the cursor exists. In Greenplum Database, all cursors
            are insensitive. This key word currently has no effect and is present for compatibility
            with the SQL standard. </pd>
        </plentry>
        <plentry>
          <pt>NO SCROLL</pt>
          <pd>A cursor cannot be used to retrieve rows in a nonsequential fashion. This is the
            default behavior in Greenplum Database, since scrollable cursors
              (<codeph>SCROLL</codeph>) are not supported.</pd>
        </plentry>
        <plentry>
          <pt>PARALLEL RETRIEVE</pt>
          <pd>Declare a parallel retrieve cursor. A parallel retrieve cursor is a special
            type of cursor that you can use to retrieve results directly from Greenplum
            Database segments, in parallel.</pd>
        </plentry>
        <plentry>
          <pt>WITH HOLD</pt>
          <pt>WITHOUT HOLD</pt>
          <pd><codeph>WITH HOLD</codeph> specifies that the cursor may continue to be used after the
            transaction that created it successfully commits. <codeph>WITHOUT HOLD</codeph>
            specifies that the cursor cannot be used outside of the transaction that created it.
              <codeph>WITHOUT HOLD</codeph> is the default.
          <note>Greenplum Database does not support declaring a
            <codeph>PARALLEL RETRIEVE</codeph> cursor with the <codeph>WITH HOLD</codeph>
            clause. <codeph>WITH HOLD</codeph> also
            cannot not be specified when the <codeph>query</codeph>
            includes a <codeph>FOR UPDATE</codeph> or <codeph>FOR SHARE</codeph> clause.</note> </pd>
        </plentry>
        <plentry>
          <pt>
            <varname>query</varname>
          </pt>
          <pd>A <codeph><xref href="./SELECT.xml#topic1" type="topic" format="dita"/></codeph> or
                <codeph><xref href="./VALUES.xml#topic1" type="topic" format="dita"/></codeph>
            command which will provide the rows to be returned by the cursor.<p>If the cursor is
              used in the <codeph>WHERE CURRENT OF</codeph> clause of the <codeph><xref
                  href="./UPDATE.xml#topic1" type="topic" format="dita"/></codeph> or <codeph><xref
                  href="./DELETE.xml#topic1" type="topic" format="dita"/></codeph> command, the
                <codeph>SELECT</codeph> command must satisfy the following conditions:</p><ul
              id="ul_rq1_vr2_m4">
              <li id="cm153794">Cannot reference a view or external table.</li>
              <li id="cm153795">References only one table. <p>The table must be updatable. For
                  example, the following are not updatable: table functions, set-returning
                  functions, append-only tables, columnar tables.</p></li>
              <li id="cm153797">Cannot contain any of the following:<ul id="ul_phn_nvj_dp">
                  <li>A grouping clause</li>
                  <li>A set operation such as <codeph>UNION ALL</codeph> or <codeph>UNION
                      DISTINCT</codeph></li>
                  <li>A sorting clause</li>
                  <li>A windowing clause</li>
                  <li>A join or a self-join</li>
                </ul><p>Specifying the <codeph>FOR UPDATE</codeph> clause in the
                    <codeph>SELECT</codeph> command prevents other sessions from changing the rows
                  between the time they are fetched and the time they are updated. Without the
                    <codeph>FOR UPDATE</codeph> clause, a subsequent use of the
                    <codeph>UPDATE</codeph> or <codeph>DELETE</codeph> command with the
                    <codeph>WHERE CURRENT OF</codeph> clause has no effect if the row was changed
                  since the cursor was created. </p><note>Specifying the <codeph>FOR UPDATE</codeph>
                  clause in the <codeph>SELECT</codeph> command locks the entire table, not just the
                  selected rows. </note></li>
            </ul></pd>
        </plentry>
      </parml>
      <parml>
        <plentry>
          <pt>FOR READ ONLY</pt>
          <pd><codeph>FOR READ ONLY</codeph> indicates that the cursor is used in a read-only
            mode.</pd>
        </plentry>
      </parml>
    </section>
    <section id="section5">
      <title>Notes</title>
      <p>Unless <codeph>WITH HOLD</codeph> is specified, the cursor created by this command can only
        be used within the current transaction. Thus, <codeph>DECLARE</codeph> without <codeph>WITH
          HOLD</codeph> is useless outside a transaction block: the cursor would survive only to the
        completion of the statement. Therefore Greenplum Database reports an error if this command
        is used outside a transaction block. Use <codeph>BEGIN</codeph> and <codeph>COMMIT</codeph>
        (or <codeph>ROLLBACK</codeph>) to define a transaction block.</p>
      <p>If <codeph>WITH HOLD</codeph> is specified and the transaction that created the cursor
        successfully commits, the cursor can continue to be accessed by subsequent transactions in
        the same session. (But if the creating transaction ends prematurely, the cursor is
        removed.) A cursor created with <codeph>WITH HOLD</codeph> is closed when an explicit
          <codeph>CLOSE</codeph> command is issued on it, or the session ends. In the current
        implementation, the rows represented by a held cursor are copied into a temporary file or
        memory area so that they remain available for subsequent transactions. </p>
      <p>If you create a cursor with the <codeph>DECLARE</codeph> command in a transaction, you
        cannot use the <codeph>SET</codeph> command in the transaction until you close the cursor
        with the <codeph>CLOSE</codeph> command.</p>
      <p>Scrollable cursors are not currently supported in Greenplum Database. You can only use
          <codeph>FETCH</codeph> or <codeph>RETRIEVE</codeph> to move the cursor position forward, not backwards.</p>
      <p><codeph>DECLARE...FOR UPDATE</codeph> is not supported with append-optimized tables.</p>
      <p>You can see all available cursors by querying the
        <codeph><xref href="../system_catalogs/pg_cursors.xml">pg_cursors</xref></codeph>
        system view.</p>
    </section>
    <section id="section6">
      <title>Examples</title>
      <p>Declare a cursor: </p>
      <codeblock>DECLARE mycursor CURSOR FOR SELECT * FROM mytable;</codeblock>
      <p>Declare a parallel retrieve cursor for the same query: </p>
      <codeblock>DECLARE myprcursor PARALLEL RETRIEVE CURSOR FOR SELECT * FROM mytable;</codeblock>
    </section>
    <section id="section7">
      <title>Compatibility</title>
      <p>SQL standard allows cursors only in embedded SQL and in modules. Greenplum Database permits
        cursors to be used interactively. </p>
      <p>Greenplum Database does not implement an <codeph>OPEN</codeph> statement for cursors. A
        cursor is considered to be open when it is declared.</p>
      <p>The SQL standard allows cursors to move both forward and backward. All Greenplum Database
        cursors are forward moving only (not scrollable).</p>
      <p>Binary cursors are a Greenplum Database extension. </p>
      <p>The SQL standard makes no provisions for parallel retrieve cursors.</p>
    </section>
    <section id="section8">
      <title>See Also</title>
      <p><codeph><xref href="CLOSE.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./DELETE.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./FETCH.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./MOVE.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./RETRIEVE.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./SELECT.xml#topic1" type="topic" format="dita"/></codeph>, <codeph><xref
            href="./UPDATE.xml#topic1" type="topic" format="dita"/></codeph></p>
    </section>
  </body>
</topic>
